#include "IR_Funcion.h"
#include "HardWare.h"
#include "OPA.h"
#include "ADC.h"
#include "UART.h"
#include "timer.h"
#include "LED.h"
#include "EEPROM.h"

const uint16 TAB_IR_THRESHOLD_OFFSET_NORMAL[C_MAX_IDX_SENS] = {55,110,155,187,210,225,240,250,260,265,273,278,282,285,288,290,293,294,296,297,298,299,301,302,303,304,};
const uint16 TAB_IR_THRESHOLD_OFFSET_LONG[C_MAX_IDX_SENS] = {160,320,451,544,611,655,699,728,757,772,795,810,822,831,840,846,855,858,864,867,870,873,879,882,885,888,};

bit F_IR_Active = NO;
// uint8 IR_PowerSel;// = C_ISINK_82MA;
// uint8 IR_Gain_Sel;// = C_LONG_DISTANCE;
uint8 IR_DistanceMode;
uint16 IR_Threshold;// = C_DEFAULT_THRESHOLD;
uint16 IR_Threshold_Off;
uint8 IR_SensIdx;

//-------- 灌电流设置：10 + 6 * idata (mA)-------//
void    ISinkCurrentSet(u8 current_set)
{
    if(current_set >= 63) current_set = 63;
    _idata = current_set;
}

void    init_IRFunction(void)
{
    P_PWR_IRRX = HIGH;

    GCC_DELAY(100);
    SEL_PA6_GPIO();
    SEL_PA5_OPA0P();
    SEL_PA7_OPA0O();

    SEL_PA4_OPA1P();
    // SEL_PA4_GPIO();
    SEL_PA3_GPIO();
    SEL_PA1_OPA1O();

    initOPA0();
    initOPA1();
    initCMP();
}

uint16 Diff_IR;

#if 0
uint8   IR_Detect(uint8 current,uint8 long_or_short,uint16 threshold_on, uint16 threshold_off)
{   
    uint8 loop = 8;
    uint8 cnt_active = 0;
    // uint8 cntTimeOut = 0;

    do{
        vuint8 i;
        // bit f_cpout;

        loop--;

        //-------- ADC 初始化 --------//
        initADC();
        SelectADCChannel(ADC0_OPA1O);
        // SelectADCChannel(ADC0_OPA0O);

        //-------- 感应参数设定 --------//
        if(long_or_short)   
        {
        //---- 长距 ----//
            OPA0_X20();
            OPA1_X30();
        }
        else
        {
        //---- 正常距离 ----//
            OPA0_X60();
            OPA1_X1();
        }
        ISinkCurrentSet(current);

        //-------- IR Detect --------//
        //---- 开启 OPA ----//
        IR_RXLED_ON();
        // GCC_DELAY(200);
        GCC_DELAY(500);

        // //---- 读取零点值 ----//
        AdcTXOFF = ADConverter();
        AdcTXOFF = ADConverter();
#if 0
        //******** 采用比较器判断是否有信号 ********//
        //---- 打开比较器 ----//
// P_TEST2 = 0;
        DeInitADC();
        // _opdda = (AdcTXOFF>>2) + 50;
        _opdda = 200;
        CMP_ON();
        GCC_DELAY(20);
        f_cpout = 0;
        cntTimeOut = 0;
        IR_TXLED_ON();  
        GCC_DELAY(200);
        while(1)
        {
            if(_opdcout == 1)
            {
                f_cpout = 1;
                P_TEST2 = 1;
                break;
            }
            else
            {
                cntTimeOut++;
                if(cntTimeOut >= 250)
                {
                    cntTimeOut = 0;
                    P_TEST2 = 0;
                    break;
                }
            } 
        }
        IR_TXLED_OFF();
        IR_RXLED_OFF();
        CMP_OFF();

        
        if(F_IR_Active == NO)
        {
        //---- IR无效 --> 检测是否有信号 ----// 
            if(f_cpout)
            {
                cnt_active++;
            }
            else
            {
                if(loop == 7)   
                loop = 0;
            }
        }
        else
        {
        //---- IR有效 --> 检测是否信号消失 ----//
            if(f_cpout == 0)
            {
                cnt_active++;
            }
            else
            {
                if(loop == 7)   
                    loop = 0;
            }
        }
        //****************************************//
#else
        // //---- 读取发射值 ----//
        IR_TXLED_ON();  
        // GCC_DELAY(100);
        AdcTXON = 0;
        for(i=0; i<3; i++)
        {
            uint16 temp;
            temp = ADConverter();
            if(temp >= AdcTXON)
            {
                AdcTXON = temp;
            }
        }

        // //---- 关闭 ISINK，OPA和ADC ----//
        IR_TXLED_OFF();
        IR_RXLED_OFF();
        DeInitADC();


        //---- 判定是否有效感应 ----//
        if(AdcTXON >= AdcTXOFF)
        {
            Diff_IR = AdcTXON - AdcTXOFF;
        }
        else
        {
            Diff_IR = 0;
        }

        if(F_IR_Active == NO)
        {
        //---- IR无效 --> 检测是否有信号 ----// 
            if(Diff_IR >= threshold_on)
            {
                cnt_active++;
            }
            else
            {
                if(loop == 7)   
                loop = 0;
            }
        }
        else
        {
        //---- IR有效 --> 检测是否信号消失 ----//
            if(Diff_IR < threshold_off)
            {
                cnt_active++;
            }
            else
            {
                if(loop == 7)   
                    loop = 0;
            }
        }
#endif
        if(loop)
        {
            // DelayXmSec(8);
            Delay10us(75);
            Delay10us(8-loop);
        }
    }while(loop);

    IR_RXLED_OFF();

    if(cnt_active >= C_DBC_TIMES)
    {
        F_IR_Active = ~F_IR_Active;
    }

    return F_IR_Active;
}
#else
// uint8   IR_Detect(uint8 long_or_short,uint16 threshold_on, uint16 threshold_off)
// {   
//     uint8 loop = 8;
//     uint8 cnt_active = 0;

//     do{
//         vuint8 i;

//         loop--;

//         //-------- ADC 初始化 --------//
//         initADC();
//         SelectADCChannel(ADC0_OPA1O);
//         // SelectADCChannel(ADC0_OPA0O);

//         //-------- 感应参数设定 --------//
//         if(long_or_short)   
//         {
//         //---- 长距 ----//
//             OPA0_X20();
//             OPA1_X30();
//             ISinkCurrentSet(C_ISINK_LONG);
//         }
//         else
//         {
//         //---- 正常距离 ----//
//             OPA0_X60();
//             OPA1_X1();
//             ISinkCurrentSet(C_ISINK_NORMAL);
//         }

//         //-------- IR Detect --------//
//         //---- 开启 OPA ----//
//         IR_RXLED_ON();
//         // GCC_DELAY(200);
//         GCC_DELAY(500);

//         // //---- 读取零点值 ----//
//         AdcTXOFF = ADConverter();
//         AdcTXOFF = ADConverter();

//         // //---- 读取发射值 ----//
//         IR_TXLED_ON();  
//         // GCC_DELAY(100);
//         AdcTXON = 0;
//         for(i=0; i<3; i++)
//         {
//             uint16 temp;
//             temp = ADConverter();
//             if(temp >= AdcTXON)
//             {
//                 AdcTXON = temp;
//             }
//         }

//         // //---- 关闭 ISINK，OPA和ADC ----//
//         IR_TXLED_OFF();
//         IR_RXLED_OFF();
//         DeInitADC();


//         //---- 判定是否有效感应 ----//
//         if(AdcTXON >= AdcTXOFF)
//         {
//             Diff_IR = AdcTXON - AdcTXOFF;
//         }
//         else
//         {
//             Diff_IR = 0;
//         }

//         if(F_IR_Active == NO)
//         {
//         //---- IR无效 --> 检测是否有信号 ----// 
//             if(Diff_IR >= threshold_on)
//             {
//                 cnt_active++;
//             }
//             else
//             {
//                 if(loop == 7)   
//                 loop = 0;
//             }
//         }
//         else
//         {
//         //---- IR有效 --> 检测是否信号消失 ----//
//             if(Diff_IR < threshold_off)
//             {
//                 cnt_active++;
//             }
//             else
//             {
//                 if(loop == 7)   
//                     loop = 0;
//             }
//         }

//         if(loop)
//         {
//             // DelayXmSec(8);
//             Delay10us(75);
//             Delay10us(8-loop);
//         }
//     }while(loop);

//     IR_RXLED_OFF();

//     if(cnt_active >= C_DBC_TIMES)
//     {
//         F_IR_Active = ~F_IR_Active;
//     }

//     return F_IR_Active;
// }
uint8   IR_Detect(void)
{   
    uint8 loop = 8;
    uint8 cnt_active = 0;

    do{
        vuint8 i;

        loop--;

        //-------- ADC 初始化 --------//
        initADC();

        SelectADCChannel(ADC0_OPA1O);
        // SelectADCChannel(ADC0_OPA0O);

        //-------- 感应参数设定 --------//
        if(IR_DistanceMode)   
        {
        //---- 长距 ----//
            OPA0_X20();
            OPA1_X30();
            ISinkCurrentSet(C_ISINK_LONG);
        }
        else
        {
        //---- 正常距离 ----//
            OPA0_X60();
            OPA1_X1();
            ISinkCurrentSet(C_ISINK_NORMAL);
        }

        //-------- IR Detect --------//
        //---- 开启 OPA ----//
        IR_RXLED_ON();
        // GCC_DELAY(200);
        GCC_DELAY(500);

        // //---- 读取零点值 ----//
        AdcTXOFF = ADConverter();
        AdcTXOFF = ADConverter();

        // //---- 读取发射值 ----//
        IR_TXLED_ON();  
        // GCC_DELAY(100);
        AdcTXON = 0;
        for(i=0; i<3; i++)
        {
            uint16 temp;
            temp = ADConverter();
            if(temp >= AdcTXON)
            {
                AdcTXON = temp;
            }
        }

        // //---- 关闭 ISINK，OPA和ADC ----//
        IR_TXLED_OFF();
        IR_RXLED_OFF();
        DeInitADC();


        //---- 判定是否有效感应 ----//
        if(AdcTXON >= AdcTXOFF)
        {
            Diff_IR = AdcTXON - AdcTXOFF;
        }
        else
        {
            Diff_IR = 0;
        }

        if(F_IR_Active == NO)
        {
        //---- IR无效 --> 检测是否有信号 ----// 
            if(Diff_IR >= IR_Threshold)
            {
                cnt_active++;
            }
            else
            {
                if(loop == 7)   
                loop = 0;
            }
        }
        else
        {
        //---- IR有效 --> 检测是否信号消失 ----//
            if(Diff_IR < IR_Threshold_Off)
            {
                cnt_active++;
            }
            else
            {
                if(loop == 7)   
                    loop = 0;
            }
        }

        if(loop)
        {
            // DelayXmSec(8);
            Delay10us(75);
            Delay10us(8-loop);
        }
    }while(loop);

    IR_RXLED_OFF();

    if(cnt_active >= C_DBC_TIMES)
    {
        F_IR_Active = ~F_IR_Active;                    
    }

    return F_IR_Active;
}
#endif

uint8 CarryDetect(void)
{
    vuint16 cntPulse = 0;
    // vuint8 cntDbcPulse = 0;
    // vuint8 cntDbcPulseL = 0;
    volatile bit f_opdcout;

#if _CARRY_DET_TIME_450US_
//---- 450us ----//
    _ptm2c0 = 0b00100000;   // fH/16 = 8M/16 = 500K --> 2us
    // _ptm2c1 = 0b01100000;   // 输入捕捉
    // _muxsel = 0b10000000;   // PTP2I来自内部接近感应电路
    _ptm2c1 = 0b11000000;
    _ptm2rpl = 225;
    _ptm2rph = 0;         // max period 225*2us = 450us
#else
    _ptm2c0 = 0b00000000;   // fsys/4 = 8M/4 = 2M --> 0.5us
    _ptm2c1 = 0b11000000;
    _ptm2rpl = 0xC2;
    _ptm2rph = 0x01;         // (01C2=450)*0.5us = 225us;
#endif
    _ptm2al = 0;
    _ptm2ah = 0;

    _ptm2af = 0;
    _ptm2pf = 0;


    if(_opdcout)    f_opdcout = 1;
    else            f_opdcout = 0;
    _pt2on = 1;
    while(_ptm2pf == 0)
    {
        GCC_CLRWDT();
        // GCC_DELAY(10);
        if(_opdcout == 1)       // 等待信号消失
        {
            // cntDbcPulseL = 0;
            // cntDbcPulse++;
            // if(cntDbcPulse >= 3)
            // {
            //     cntDbcPulse = 0;
                if(f_opdcout == 0)
                {
                    f_opdcout = 1;
                }
            // }
        }
        else
        {
            // cntDbcPulse = 0;
            // cntDbcPulseL++;
            // if(cntDbcPulseL >= 3)
            // {
            //     cntDbcPulseL = 0;
                if(f_opdcout)
                {
                    f_opdcout = 0;
                    cntPulse++;
                }
            // }
        }
    }
    _pt2on = 0;

#if _CARRY_DET_TIME_450US_
    if((cntPulse >= 1)&&(cntPulse < 4))   return 1;
#else
    if((cntPulse >= 1)&&(cntPulse < 3))   return 1;
#endif
    else                return 0;
}


uint8 IR_Sm = 0;
uint16 IR_Width = 0;
uint8 IR_RecvCount = 0;
uint8 IR_RecvBuf[2];
uint8 IR_RemoteCmd = 0;

const uint8 TAB_BIT_IR[] = {0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};

uint8 IR_RemoteDetect(void)
{
    bit     result = 0;
    bit     f_carry;

    OPA0_X60();
    OPA1_X1();

    IR_RXLED_ON();
    _opdsw23 = 1;
    _opdcen = 1;


    IR_Sm = 0;

    do{
        f_carry = CarryDetect();
        switch(IR_Sm)
        {
            //---- 检测载波 ----//
            case 0:
                if(f_carry)
                {
                    IR_Sm++;
                }
                else
                    break;

            //---- 检测引导码 ----//
            case 1:
                IR_Width++;
                if(f_carry == 0)
                {
                    if(IR_Width >= C_TM_IR_HEAD_H)
                    {
                        IR_Sm++;
                    }
                    else
                    {
                        IR_Sm = 0;
                    }
                    IR_Width = 0;
                }
            break;

            //---- 检测引导码低位 ----//
            case 2:
                IR_Width++;
                if(f_carry == 1)
                {
                    if((IR_Width >= C_TM_IR_HEAD_L_MIN) && (IR_Width < C_TM_IR_HEAD_L_MAX))
                    {
                        IR_Sm++;
                    }
                    else
                    {
                        IR_Sm = 0;
                    }
                    IR_Width = 0;
                }
            break;

            //---- 检测数据同步位 ----//
            case 3:
                IR_Width++;
                if(f_carry == 0)
                {
                    if((IR_Width >= C_TM_IR_DATA_SYNC_MIN) && (IR_Width < C_TM_IR_DATA_SYNC_MAX))
                    {
                        IR_Sm++;
                    }
                    else
                    {
                        IR_Sm = 0;
                    }
                    IR_Width = 0;
                }
            break;

            //---- 检测数据位 ----//
            case 4:
                IR_Width++;
                if(f_carry == 1)
                {
                    if((IR_Width >= C_TM_IR_DATA_MIN) && (IR_Width <= C_TM_IR_DATA_MAX))
                    {
                        if(IR_Width >= C_TM_IR_DATA_0_1)
                        {
                            IR_RecvBuf[IR_RecvCount>>3] |= TAB_BIT_IR[IR_RecvCount&0x07];
                        }
                        else
                        {
                            IR_RecvBuf[IR_RecvCount>>3] &= ~TAB_BIT_IR[IR_RecvCount&0x07];
                        }
          
                        IR_RecvCount++;
                        if(IR_RecvCount >= 16)
                        {
                            IR_RecvCount = 0;
                            if((IR_RecvBuf[0] ^ IR_RecvBuf[1]) == 0xFF)
                            {
                                IR_RemoteCmd = IR_RecvBuf[0];
                            }

                            IR_Sm = 0;
                            result = 1;
                        }
                        else
                        {
                            IR_Sm--;
                        }
                    }
                    else
                    {
                        IR_Sm = 0;
                    }
                    IR_Width = 0;
                }
            break;

            //---- 结束 ----//
            default:
            break;
        }   
    }while(IR_Sm);

    // IR_RXLED_OFF();
    _opdsw23 = 0;
    _opdcen = 0;
    return result;

}


void    IR_UpdateSensitivity(void)
{
    if(IR_DistanceMode == C_NORMAL_DISTANCE)
        IR_Threshold = C_MAX_IR_VALUE_NORMAL - TAB_IR_THRESHOLD_OFFSET_NORMAL[IR_SensIdx];
    else
        IR_Threshold = C_MAX_IR_VALUE_LONG - TAB_IR_THRESHOLD_OFFSET_LONG[IR_SensIdx];

    // IR_Threshold_Off = IR_Threshold * 3 / 4;
    IR_Threshold_Off = IR_Threshold * 15 / 16;
}

void    IR_DistanceSetting(uint8 op)
{
    if(op == 0)
    {
    //---- 距离减 ----//
        if(IR_SensIdx)  IR_SensIdx--;
    }
    else
    {
    //---- 距离加 ----//
        if(IR_SensIdx < C_MAX_IDX_SENS_NORMAL - 1)
        {
            IR_SensIdx++;
        }
    }

    // EEPROM_Write();
}

uint8    IR_StudyDistance(void)
{
    bit f_study_ok = 0;
    uint8 bk_DistanceMode;
    uint8 bk_SensIdx;
    // IR_PowerSel = C_ISINK_16MA;
    // IR_Gain_Sel = C_NORMAL_DISTANCE;

    bk_SensIdx = IR_SensIdx;
    bk_DistanceMode = IR_DistanceMode;

    IR_SensIdx = 0;
    IR_DistanceMode = C_NORMAL_DISTANCE;

    //---- 最低灵敏度开始搜索 ----//
    while(!f_study_ok)
    {
        IR_UpdateSensitivity();
        // if(IR_Detect(IR_PowerSel, IR_Gain_Sel, IR_Threshold, IR_Threshold_Off))
        // if(IR_Detect(IR_DistanceMode, IR_Threshold, IR_Threshold_Off))
        if(IR_Detect())
        {
            f_study_ok = 1;
            break;
        }
        if(IR_SensIdx < C_MAX_IDX_SENS_NORMAL - 1)
            IR_SensIdx++;
        else
        {
            break;
        }

		LED_ON();
		DelayXmSec(50*T1MS);
		LED_OFF();
		DelayXmSec(200*T1MS);
        // LED_Flash(1,50,200);
    }
    
    if(f_study_ok == 0)
    {
        // IR_PowerSel = C_ISINK_82MA;
        // IR_Gain_Sel = C_LONG_DISTANCE;
        IR_SensIdx = 0;
        IR_DistanceMode = C_LONG_DISTANCE;
        while(!f_study_ok)
        {
            IR_UpdateSensitivity();
            // if(IR_Detect(IR_PowerSel, IR_Gain_Sel, IR_Threshold, IR_Threshold_Off))
            // if(IR_Detect(IR_DistanceMode, IR_Threshold, IR_Threshold_Off))
            if(IR_Detect())
            {
                f_study_ok = 1;
                break;
            }
            if(IR_SensIdx < C_MAX_IDX_SENS_LONG - 1)
                IR_SensIdx++;
            else
            {
                break;
            }

            LED_ON();
            DelayXmSec(50*T1MS);
            LED_OFF();
            DelayXmSec(200*T1MS);
            // LED_Flash(1,50,200);
        }
    }

    if(!f_study_ok)
    {
        IR_SensIdx = bk_SensIdx;
        IR_DistanceMode = bk_DistanceMode;
    }
    return f_study_ok;
}